package gov.pbc.nn.kjgl.fxq.riskAssess.view;

import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.exception.NoneLoginException;
import com.bstek.bdf2.core.orm.hibernate.ISessionCallback;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
import com.bstek.dorado.uploader.UploadFile;
import com.bstek.dorado.uploader.annotation.FileResolver;

import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.dao.CommonHibernateDao;
import gov.pbc.nn.kjgl.fxq.attachment.GBKOrder;
import gov.pbc.nn.kjgl.fxq.riskAssess.entity.RiskAssessIndexEntity;
import gov.pbc.nn.kjgl.fxq.riskAssess.entity.RiskAssessIndexTemplateEntity;
import gov.pbc.nn.kjgl.fxq.workDocument.view.WorkDocumentPR;

@Component(RiskAssessIndexPR.BEAN_ID)
public class RiskAssessIndexPR extends CommonHibernateDao {
	public static final String BEAN_ID = "riskAssessIndexPR";

	@Resource(name = WorkDocumentPR.BEAN_ID)
	private WorkDocumentPR workDocumentPR;
	
	@DataProvider
	public Collection<?> getIndexTemplates(Map<String, String> parameter) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		Dept dept = (Dept) user.getDepts().get(0);
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(RiskAssessIndexTemplateEntity.class);
		detachedCriteria.add(Restrictions.eq("deptId", dept.getCDept().getId()));
		detachedCriteria.add(Restrictions.eq("invalid", false));
		detachedCriteria.addOrder(Order.desc("createDate"));
		if (parameter != null && StringUtils.isNoneBlank(parameter.get("filterValue"))) {
			String filterValue = parameter.get("filterValue").replace(' ', '%');
			detachedCriteria.add(Restrictions.like("name", "%" + filterValue + "%"));
		}
		return this.query(detachedCriteria);
	}

	@DataProvider
	public void loadAllRiskAssessIndexTemplates(Page<RiskAssessIndexTemplateEntity> page, Criteria criteria) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		Dept dept = (Dept) user.getDepts().get(0);
		DetachedCriteria detachedCriteria = this.buildDetachedCriteria(criteria, RiskAssessIndexTemplateEntity.class);
		detachedCriteria.add(Restrictions.eq("deptId", dept.getCDept().getId()));
		detachedCriteria.add(Restrictions.eq("invalid", false));
		if (criteria != null && criteria.getOrders() != null && !criteria.getOrders().isEmpty()) {
			com.bstek.dorado.data.provider.Order order = criteria.getOrders().get(0);
			if (order.isDesc()) {
				detachedCriteria.addOrder(Order.desc(order.getProperty()));
			} else {
				detachedCriteria.addOrder(Order.asc(order.getProperty()));
			}
		} else {
			detachedCriteria.addOrder(Order.desc("createDate"));
		}
		this.pagingQuery(page, detachedCriteria);
	}

	@DataProvider
	public Collection<?> loadAllRiskAssessIndexs(String templateId) throws Exception {
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(RiskAssessIndexEntity.class);
		detachedCriteria.add(Restrictions.eq("invalid", false));
		detachedCriteria.add(Restrictions.eq("templateId", templateId));
		detachedCriteria.addOrder(GBKOrder.asc("level1Code"));
		detachedCriteria.addOrder(GBKOrder.asc("level1Content"));
		detachedCriteria.addOrder(GBKOrder.asc("level2Code"));
		detachedCriteria.addOrder(GBKOrder.asc("level2Content"));
		return this.query(detachedCriteria);
	}

	@DataResolver
	@Transactional
	public void saveRiskAssessIndexs(List<RiskAssessIndexTemplateEntity> riskAssessIndexTemplates) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		Dept dept = (Dept) user.getDepts().get(0);
		for (RiskAssessIndexTemplateEntity riskAssessIndexTemplate : riskAssessIndexTemplates) {
			EntityState state = EntityUtils.getState(riskAssessIndexTemplate);
			RiskAssessIndexTemplateEntity riskAssessIndexTemplateEntity = EntityUtils.toEntity(riskAssessIndexTemplate);
			if (state.equals(EntityState.NEW)) {
				riskAssessIndexTemplate.setDeptId(dept.getCDept().getId());
				riskAssessIndexTemplate.setDeptName(dept.getCDept().getName());
				this.save(riskAssessIndexTemplate);
			} else if (state.equals(EntityState.MODIFIED)) {
				this.update(riskAssessIndexTemplate);
			} else if (state.equals(EntityState.DELETED)) {
				this.delete(riskAssessIndexTemplate);
			}
			List<RiskAssessIndexEntity> riskAssessIndexEntities = EntityUtils.getValue(riskAssessIndexTemplateEntity, "indexs");
			if (riskAssessIndexEntities != null) {
				for (RiskAssessIndexEntity riskAssessIndexEntity : riskAssessIndexEntities) {
					riskAssessIndexEntity.setTemplateId(riskAssessIndexTemplate.getId());
					this.workDocumentPR.saveEntity(riskAssessIndexEntity);
				}
			}
		}
	}

	@Expose
	public String checkIndex(final String templateId) throws Exception {
		return this.doInHibernateSession(new ISessionCallback<String>() {

			@Override
			public String doInSession(Session session) {
				// TODO Auto-generated method stub
				String sql = " SELECT LEVEL1_CODE_ AS level1Code,LEVEL1_CONTENT_ AS level1Content,(IF(INDEX_TYPE_='一级指标',1,NULL)) AS level1Count,SUM(IF(INDEX_TYPE_='一级指标',SCORE_,0)) AS level1Score, " 
				           + " SUM(IF(INDEX_TYPE_='二级指标',SCORE_,0)) AS level2Score FROM t_fxq_risk_assess_index_enttiy WHERE	INVALID_=0 AND TEMPLATE_ID_ = :templateId " 
						   + " GROUP BY LEVEL1_CODE_,LEVEL1_CONTENT_";
				Query query = session.createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
				query.setString("templateId", templateId);
				List<Map<String, Object>> list = query.list();
				if (list == null || list.isEmpty()) {
					return "风险评估指标模板为空";
				} else {
					long sumAll = 0;
					for (Map<String, Object> map : list) {
						if ((int) map.get("level1Count") > 1) {
							return "存在" + map.get("level1Count") + "个重复指标信息[一级指标编号:" + map.get("level1Code") + ",一级指标内容:" + map.get("level1Content") + "]";
						} else if (!((BigDecimal) map.get("level1Score")).equals(((BigDecimal) map.get("level2Score")))) {
							return "[一级指标编号:" + map.get("level1Code") + ",一级指标内容:" + map.get("level1Content") + "]分值不等于其二级指标分值总和！";
						} else {
							sumAll += ((BigDecimal) map.get("level1Score")).longValue();
						}
					}
					if (sumAll!=100L) {
						return "全部指标总分不等于100分！";
					} else {
						return "";
					}
				}
			}
		});
	}

	@FileResolver
	public Map<String, Object> importData(UploadFile file, Map<String, Object> parameter) throws Exception {
		final String templateId = (String) parameter.get("templateId");
		Map<String, Object> data = new HashMap<String, Object>();
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		final Map<String, String> nameMap = new HashMap<String, String>();
		nameMap.put("指标类别", "indexType");
		//nameMap.put("体系指标编号", "systemCode");
		//nameMap.put("体系指标名称", "systemName");
		nameMap.put("一级指标编号", "level1Code");
		nameMap.put("一级指标内容", "level1Content");
		nameMap.put("二级指标编号", "level2Code");
		nameMap.put("二级指标内容", "level2Content");
		nameMap.put("满分分值", "score");
		nameMap.put("评分标准", "scoreStandard");
		nameMap.put("简要描述", "remark");
		Set<String> labelSet = new HashSet<String>();
		Iterator<String> labelIter = nameMap.keySet().iterator();
		while (labelIter.hasNext()) {
			labelSet.add(labelIter.next());
		}
		Workbook workbook;
		if (file.getFileName().toUpperCase().endsWith(".XLS")) {
			workbook = new HSSFWorkbook(file.getInputStream());
		} else if (file.getFileName().toUpperCase().endsWith(".XLSX")) {
			workbook = new XSSFWorkbook(file.getInputStream());
		} else {
			data.put("success", false);
			data.put("errorInfo", "导入文件格式错误！");
			return data;
		}
		final Sheet sheet = workbook.getSheetAt(0);
		if (sheet == null) {
			data.put("success", false);
			data.put("errorInfo", "导入文件不存在Sheet！");
			return data;
		}
		final Map<String, Integer> indexMap = new HashMap<String, Integer>();
		Row labelRow = sheet.getRow(0);
		if (labelRow == null) {
			data.put("success", false);
			data.put("errorInfo", "导入表格数据为空！");
			return data;
		}
		Iterator<Cell> iterCell = labelRow.cellIterator();
		while (iterCell.hasNext()) {
			Cell cell = iterCell.next();
			cell.setCellType(Cell.CELL_TYPE_STRING);
			String label = cell.getStringCellValue();
			if (nameMap.containsKey(label)) {
				indexMap.put(label, cell.getColumnIndex());
				labelSet.remove(label);
			}
		}
		if (!labelSet.isEmpty()) {
			data.put("success", false);
			data.put("errorInfo", "缺少列【" + labelSet.toArray()[0] + "】");
			return data;
		}
		return this.doInHibernateSession(new ISessionCallback<Map<String, Object>>() {

			@Override
			public Map<String, Object> doInSession(Session session) {
				// TODO Auto-generated method stub

				Map<String, Object> data = new HashMap<String, Object>();
				Transaction t = session.beginTransaction();
				try {
					Query query = session.createQuery("delete from RiskAssessIndexEntity where templateId=:templateId ");
					query.setString("templateId", templateId);
					query.executeUpdate();
					int rowNum = sheet.getPhysicalNumberOfRows();
					for (int i = 1; i < rowNum; i++) {
						Row row = sheet.getRow(i);
						RiskAssessIndexEntity riskAssessIndex = new RiskAssessIndexEntity();
						Iterator<String> iter = nameMap.keySet().iterator();
						while (iter.hasNext()) {
							String label = iter.next();
							String name = nameMap.get(label);
							int index = indexMap.get(label);
							Cell cell = row.getCell(index);
							cell.setCellType(Cell.CELL_TYPE_STRING);
							Object value = cell.getStringCellValue();							
							if (!name.equals("level2Code") && !name.equals("level2Content") && !name.equals("remark") && StringUtils.isBlank(value.toString())) {
								data.put("success", false);
								data.put("errorInfo", "第" + (row.getRowNum() + 1) + "行第" + (index + 1) + "列,【" + label + "】不能为空!");
								t.rollback();
								session.clear();
								return data;
							}
							Class cla = new PropertyDescriptor(name, RiskAssessIndexEntity.class).getPropertyType();							
							if (cla.getName().equals("int")) {
								try {
									value = Integer.parseInt(value.toString());
								} catch (Exception e) {
									data.put("success", false);
									data.put("errorInfo", "第" + (row.getRowNum() + 1) + "行第" + (index + 1) + "列,满分分值应为整数!");
									t.rollback();
									session.clear();
									return data;
								}
							}
							PropertyUtils.setProperty(riskAssessIndex, name, value);
						}
						if (!riskAssessIndex.getIndexType().equals("一级指标") && !riskAssessIndex.getIndexType().equals("二级指标")) {
							data.put("success", false);
							data.put("errorInfo", "第" + (row.getRowNum() + 1) + "行,指标类别应为“一级指标”或“二级指标”!");
							t.rollback();
							session.clear();
							return data;
						}
						if (riskAssessIndex.getIndexType().equals("二级指标") && (StringUtils.isBlank(riskAssessIndex.getLevel2Code()) || StringUtils.isBlank(riskAssessIndex.getLevel2Content()))) {
							data.put("success", false);
							data.put("errorInfo", "第" + (row.getRowNum() + 1) + "行,指标类别为“二级指标”,“二级指标编码”和“二级指标内容”不能为空!");
							t.rollback();
							session.clear();
							return data;
						}
						if (riskAssessIndex.getIndexType().equals("一级指标")) {
							riskAssessIndex.setLevel2Code("");
							riskAssessIndex.setLevel2Content("");
						}
						riskAssessIndex.setCreateUser(ContextHolder.getLoginUserName());
						riskAssessIndex.setCreateUserCname(ContextHolder.getLoginUser().getCname());
						riskAssessIndex.setCreateDate(new Date());
						riskAssessIndex.setTemplateId(templateId);
						session.save(riskAssessIndex);
					}
					data.put("success", true);
					data.put("errorInfo", "");
					t.commit();
					return data;
				} catch (Exception e) {
					// TODO: handle exception
					t.rollback();
					session.clear();
					data.put("success", false);
					data.put("errorInfo", e.getMessage());
					return data;
				}
			}
		});

	}

}
